(function($, window, document, undefined) {
	$.suredy = $.extend({}, $.suredy);

	var suredyTree = function($tree, data, options) {
		this.tree = $tree;
		this.data = data;
		this.options = $.extend({
			checkbox : false,
			folderCheckbox : true,
			fileCheckbox : true,
			collapseAll : undefined,
			click : undefined,
			style : 'normal', // normal|file|department
			showTitle : true
		}, options);
		this.template = {
			node : '<div class="node ${type} ${collapsed}"><div class="node-info" id=${id}><div class="pull-left text-center square">${icon}</div><div class="pull-left text-center check">${check}</div><div class="text" title="${title}">${text}</div></div>${children}</div>',
			children : '<div class="children">${children}</div>',
			icon : '<i class="icon-angle-down"></i>',
			checkbox : '<i class="icon-check-empty"></i>'
		};
		this.createNode = function(nd, l) {
			if (!nd)
				return '';

			l = l || 1;

			// is leaf
			var isFolder = nd.leaf == undefined ? (nd.children && nd.children.length > 0) : !nd.leaf;

			// node
			var html = this.template.node;

			// id
			nd._tree_id = '_id_' + (new Date().getTime() + '_' + Math.random()).replace('0.', '');
			html = html.replace(/\$\{id\}/, nd._tree_id);

			// type
			html = html.replace(/\$\{type\}/g, isFolder ? 'folder' : 'file');

			// collapsed
			var collapse = this.options.collapseAll;
			if (collapse === undefined)
				collapse = (isFolder && nd.collapse);
			html = html.replace(/\$\{collapsed\}/g, collapse ? 'collapsed' : '');

			// icon
			if ('normal' === this.options.style && !isFolder) {
				html = html.replace(/\$\{icon\}/g, '&nbsp;');
			} else
				html = html.replace(/\$\{icon\}/g, this.template.icon);

			// checkbox
			if (this.options.checkbox && ((isFolder && this.options.folderCheckbox) || (!isFolder && this.options.fileCheckbox))) {
				html = html.replace(/\$\{check\}/g, this.template.checkbox);
			} else
				html = html.replace(/\$\{check\}/g, '');

			// text
			html = html.replace(/\$\{text\}/g, nd.text);

			// title
			html = html.replace(/\$\{title\}/g, this.options.showTitle ? nd.text : '');

			// children
			var child = '';
			if (isFolder && nd.children) {
				for ( var i = 0; i < nd.children.length; i++) {
					child += this.createNode(nd.children[i], l + 1);
				}

				if (child !== '')
					child = this.template.children.replace(/\$\{children\}/, child);
			}
			html = html.replace(/\$\{children\}/g, child);

			return html;
		};
	};

	suredyTree.prototype = {
		make : function() {
			if (!this.data) {
				alert('Invalid tree data. Please check it.');
				return;
			}

			var html = '';

			for ( var i = 0; i < this.data.length; i++) {
				html += this.createNode(this.data[i]);
			}

			this.tree.html(html);

			this.binding(this.data);
		},
		binding : function(data) {
			if (!data)
				return;

			for ( var i = 0; i < data.length; i++) {
				var d = $.extend({}, data[i]);
				var children = d.children;
				var id = d._tree_id;

				// remove children data
				delete d.children;

				// binding data
				$('.suredy-tree #' + id).data('_tree_data', d);
				$('.suredy-tree #' + id).data('_tree_node_click', this.options.click);

				this.binding(children);
			}
		}
	};

	$.fn.tree = function(options, data) {
		if (data && !$.isArray(data))
			data = [ data ];

		return this.each(function(i) {
			var $this = $(this);

			if (!data) {
				var uri = $this.data('uri');

				$.ajax({
					url : uri,
					dataType : 'json',
					async : false,
					success : function(response, textStatus, jqXHR) {
						data = $.isArray(response) ? response : [ response ];
					}
				});
			}

			if (!data) {
				alert('Can not load the tree data. Please check it.');
				return;
			}

			var style = $this.hasClass('file') ? 'file' : undefined;
			style = style || ($this.hasClass('department') ? 'department' : undefined);
			style = style || 'normal';

			var tree = new suredyTree($this, data, $.extend({}, {
				style : style
			}, options));

			tree.make();
		});
	};

	$.suredy.tree = {
		data : function($node) {
			if (!$node || !($node instanceof jQuery) || !$node.hasClass('node')) {
				alert('Invalid suredy tree node.');
				return;
			}

			return $('>.node-info', $node).data('_tree_data');
		},
		checked : function($tree) {
			if (!$tree || !($tree instanceof jQuery) || !$tree.hasClass('suredy-tree')) {
				alert('It\'s not a suredy tree.');
				return;
			}

			return $('.node.checked', $tree).has('>.node-info .check>i');
		},
		selected : function($tree) {
			if (!$tree || !($tree instanceof jQuery) || !$tree.hasClass('suredy-tree')) {
				alert('It\'s not a suredy tree.');
				return;
			}

			return $('.active:first-child', $tree).parent();
		}
	};
})(jQuery, window, document);

$(function() {
	var doCollapse = function($node) {
		// only folder can be collapsed
		if (!$node.hasClass('folder'))
			return;

		if ($node.hasClass('collapsed'))
			$node.removeClass('collapsed');
		else
			$node.addClass('collapsed');
	};

	var doCheck = function($node) {
		// only has checkbox
		if ($node.has('>.node-info .check>i').length <= 0)
			return;

		if ($node.hasClass('checked')) {
			$node.removeClass('checked');
			$('.node', $node).removeClass('checked');
		} else {
			$node.addClass('checked');
			$('.node', $node).addClass('checked');
		}
	};

	// folder's icon click event
	$('.suredy-tree').delegate('.node.folder>.node-info>.square', 'click', function(event) {
		doCollapse($(this).parent().parent());
		event.stopPropagation();
	});

	// node click event
	$('.suredy-tree').delegate('.node>.node-info', 'click', function(event) {
		// remove all active class
		$('.suredy-tree .node>.node-info').removeClass('active');

		var $this = $(this);

		// make this node active
		$this.addClass('active');

		// do check
		doCheck($(this).parent());

		var click = $this.data('_tree_node_click');

		// call click event
		if ($.isFunction(click))
			click.call($this.parent());
	});

	// node dblclick event
	$('.suredy-tree').delegate('.node>.node-info', 'dblclick', function(event) {
		doCollapse($(this).parent());
	});
});